home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / graphics / gnuplot / win / wmenu.c < prev    next >
C/C++ Source or Header  |  1993-09-15  |  18KB  |  678 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: wmenu.c%v 3.50 1993/07/09 05:35:24 woo Exp $";
  3. #endif
  4.  
  5. /* GNUPLOT - win/wmenu.c */
  6. /*
  7.  * Copyright (C) 1992   Maurice Castro, Russell Lang
  8.  *
  9.  * Permission to use, copy, and distribute this software and its
  10.  * documentation for any purpose with or without fee is hereby granted, 
  11.  * provided that the above copyright notice appear in all copies and 
  12.  * that both that copyright notice and this permission notice appear 
  13.  * in supporting documentation.
  14.  *
  15.  * Permission to modify the software is granted, but not the right to
  16.  * distribute the modified code.  Modifications are to be distributed 
  17.  * as patches to released version.
  18.  *  
  19.  * This software is provided "as is" without express or implied warranty.
  20.  * 
  21.  *
  22.  * AUTHORS
  23.  * 
  24.  *   Maurice Castro
  25.  *   Russell Lang
  26.  * 
  27.  * Send your comments or suggestions to 
  28.  *  info-gnuplot@dartmouth.edu.
  29.  * This is a mailing list; to join it send a note to 
  30.  *  info-gnuplot-request@dartmouth.edu.  
  31.  * Send bug reports to
  32.  *  bug-gnuplot@dartmouth.edu.
  33.  */
  34.  
  35. #define STRICT
  36. #include <windows.h>
  37. #include <windowsx.h>
  38. #if WINVER >= 0x030a
  39. #include <commdlg.h>
  40. #endif
  41. #include <string.h>    /* only use far items */
  42. #include "wgnuplib.h"
  43. #include "wresource.h"
  44. #include "wcommon.h"
  45.  
  46. BOOL CALLBACK _export InputBoxDlgProc(HWND, UINT, WPARAM, LPARAM);
  47. LRESULT CALLBACK _export MenuButtonProc(HWND, UINT, WPARAM, LPARAM);
  48.  
  49. /* limits */
  50. #define MAXSTR 255
  51. #define MACROLEN 5000
  52. /* #define NUMMENU 256  defined in wresourc.h */
  53. #define MENUDEPTH 3
  54.  
  55. /* menu tokens */
  56. #define CMDMIN 129
  57. #define INPUT 129
  58. #define EOS 130
  59. #define OPEN 131
  60. #define SAVE 132
  61. #define CMDMAX 132
  62. char * keyword[] = {
  63.     "[INPUT]", "[EOS]", "[OPEN]", "[SAVE]",
  64.         "{ENTER}", "{ESC}", "{TAB}",
  65.         "{^A}", "{^B}", "{^C}", "{^D}", "{^E}", "{^F}", "{^G}", "{^H}", 
  66.     "{^I}", "{^J}", "{^K}", "{^L}", "{^M}", "{^N}", "{^O}", "{^P}", 
  67.     "{^Q}", "{^R}", "{^S}", "{^T}", "{^U}", "{^V}", "{^W}", "{^X}", 
  68.     "{^Y}", "{^Z}", "{^[}", "{^\\}", "{^]}", "{^^}", "{^_}",
  69.     NULL};
  70. BYTE keyeq[] = {
  71.     INPUT, EOS, OPEN, SAVE,
  72.         13, 27, 9,
  73.         1, 2, 3, 4, 5, 6, 7, 8,
  74.     9, 10, 11, 12, 13, 14, 15, 16,
  75.     17, 18, 19, 20, 21, 22, 23, 24, 
  76.     25, 26, 28, 29, 30, 31,
  77.     NULL};
  78.  
  79.  
  80. /* Send a macro to the text window */
  81. void
  82. SendMacro(LPTW lptw, UINT m)
  83. {
  84. BYTE FAR *s;
  85. char *d;
  86. char *buf;
  87. BOOL flag=TRUE;
  88. int i;
  89. LPMW lpmw = lptw->lpmw;
  90. #if WINVER >= 0x030a
  91. OPENFILENAME ofn;
  92. char *szTitle;
  93. char *szFile;
  94. char *szFilter;
  95. #endif
  96.  
  97.     if ( (buf = LocalAllocPtr(LHND, MAXSTR+1)) == (char *)NULL )
  98.         return;
  99.  
  100.     if (m>=lpmw->nCountMenu)
  101.         return;
  102.     s = lpmw->macro[m];
  103.     d = buf;
  104.     *d = '\0';
  105.     while (s && *s && (d-buf < MAXSTR)) {
  106.         if (*s>=CMDMIN  && *s<=CMDMAX) {
  107.         switch (*s) {
  108.             case SAVE: /* [SAVE] - get a save filename from a file list box */
  109.             case OPEN: /* [OPEN] - get a filename from a file list box */
  110. #if WINVER >= 0x030a
  111.                 /* This uses COMMDLG.DLL from Windows 3.1 
  112.                    COMMDLG.DLL is redistributable */
  113.                 {
  114.                 BOOL save;
  115.                 if ( (szTitle = LocalAllocPtr(LHND, MAXSTR+1)) == (char *)NULL )
  116.                     return;
  117.                 if ( (szFile = LocalAllocPtr(LHND, MAXSTR+1)) == (char *)NULL )
  118.                     return;
  119.                 if ( (szFilter = LocalAllocPtr(LHND, MAXSTR+1)) == (char *)NULL )
  120.                     return;
  121.  
  122.                 save = (*s==SAVE);
  123.                 s++;
  124.                         for(i=0; (*s >= 32 && *s <= 126); i++)
  125.                             szTitle[i] = *s++;    /* get dialog box title */
  126.                 szTitle[i]='\0';
  127.                 s++;
  128.                         for(i=0; (*s >= 32 && *s <= 126); i++)
  129.                             szFile[i] = *s++;    /* temporary copy of filter */
  130.                 szFile[i++]='\0';
  131.                 lstrcpy(szFilter,"Default (");
  132.                 lstrcat(szFilter,szFile);
  133.                 lstrcat(szFilter,")");
  134.                 i=lstrlen(szFilter);
  135.                 i++;    /* move past NULL */
  136.                 lstrcpy(szFilter+i,szFile);
  137.                 i+=lstrlen(szFilter+i);
  138.                 i++;    /* move past NULL */
  139.                 lstrcpy(szFilter+i,"All Files (*.*)");
  140.                 i+=lstrlen(szFilter+i);
  141.                 i++;    /* move past NULL */
  142.                 lstrcpy(szFilter+i,"*.*");
  143.                 i+=lstrlen(szFilter+i);
  144.                 i++;    /* move past NULL */
  145.                 szFilter[i++]='\0';    /* add a second NULL */
  146.                 flag = 0;
  147.  
  148.                 /* the Windows 3.1 implentation - MC */
  149.                 szFile[0] = '\0';
  150.                 /* clear the structrure */
  151.                 _fmemset(&ofn, 0, sizeof(OPENFILENAME));
  152.                 ofn.lStructSize = sizeof(OPENFILENAME);
  153.                 ofn.hwndOwner = lptw->hWndParent;
  154.                 ofn.lpstrFilter = szFilter;
  155.                 ofn.nFilterIndex = 1;
  156.                 ofn.lpstrFile = szFile;
  157.                 ofn.nMaxFile = MAXSTR;
  158.                 ofn.lpstrFileTitle = szFile;
  159.                 ofn.nMaxFileTitle = MAXSTR;
  160.                 ofn.lpstrTitle = szTitle;
  161.                 ofn.lpstrInitialDir = (LPSTR)NULL;
  162.                 ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
  163.                 flag = (save ? GetSaveFileName(&ofn) : GetOpenFileName(&ofn));
  164.                 if( flag ) {
  165.                     lpmw->nChar = lstrlen(ofn.lpstrFile);
  166.                     for (i=0; i<lpmw->nChar; i++)
  167.                         *d++=ofn.lpstrFile[i];
  168.                 }
  169.  
  170.                 LocalFreePtr((void NEAR *)OFFSETOF(szTitle));
  171.                 LocalFreePtr((void NEAR *)OFFSETOF(szFilter));
  172.                 LocalFreePtr((void NEAR *)OFFSETOF(szFile));
  173.  
  174.                 }
  175.                 break;
  176. #else
  177.                 /* Use InputBox if you don't have COMMDLG.DLL.
  178.                 s++;    /* skip list box title */
  179.                 for(i=0; (*s >= 32 && *s <= 126); i++)
  180.                     s++;
  181. #endif
  182.             case INPUT: /* [INPUT] - input a string of characters */
  183.                 s++;
  184.                 for(i=0; (*s >= 32 && *s <= 126); i++)
  185.                     lpmw->szPrompt[i] = *s++;
  186.                 lpmw->szPrompt[i]='\0';
  187. #ifdef __DLL__
  188.                 lpmw->lpProcInput = (DLGPROC)GetProcAddress(hdllInstance, "InputBoxDlgProc");
  189. #else
  190.                 lpmw->lpProcInput = (DLGPROC)MakeProcInstance((FARPROC)InputBoxDlgProc, hdllInstance);
  191. #endif
  192.                 flag = DialogBox( hdllInstance, "InputDlgBox", lptw->hWndParent, lpmw->lpProcInput);
  193.                 if( flag ) {
  194.                     for (i=0; i<lpmw->nChar; i++)
  195.                         *d++=lpmw->szAnswer[i];
  196.                 }
  197. #ifndef __DLL__
  198.                 FreeProcInstance((FARPROC)lpmw->lpProcInput);
  199. #endif
  200.                 break;
  201.             case EOS: /* [EOS] - End Of String - do nothing */
  202.                 default:
  203.                 s++;
  204.                 break;
  205.         }
  206.         if (!flag) { /* abort */
  207.             d = buf;
  208.             s = (BYTE FAR *)"";
  209.         }
  210.         }
  211.         else {
  212.         *d++ = *s++;
  213.         }
  214.     }
  215.     *d = '\0';
  216.     if (buf[0]!='\0') {
  217.         d = buf;
  218.         while (*d) {
  219.             SendMessage(lptw->hWndText,WM_CHAR,*d,1L);
  220.             d++;
  221.         }
  222.     }
  223. }
  224.  
  225.  
  226. #define GBUFSIZE 512
  227. typedef struct tagGFILE {
  228.     HFILE    hfile;
  229.     char     getbuf[GBUFSIZE];
  230.     int    getnext;
  231.     int    getleft;
  232. } GFILE;
  233.  
  234. GFILE * Gfopen(LPSTR lpszFileName, int fnOpenMode)
  235. {
  236. GFILE *gfile;
  237.     
  238.     gfile = (GFILE *)LocalAllocPtr(LHND, sizeof(GFILE));
  239.     if (!gfile)
  240.         return NULL;
  241.  
  242.     gfile->hfile = _lopen(lpszFileName, fnOpenMode);
  243.     if (gfile->hfile == HFILE_ERROR) {
  244.         LocalFreePtr((void NEAR *)OFFSETOF(gfile));
  245.         return NULL;
  246.     }
  247.     gfile->getleft = 0;
  248.     gfile->getnext = 0;
  249.     return gfile;
  250. }
  251.  
  252. void Gfclose(GFILE * gfile)
  253. {
  254.     
  255.     _lclose(gfile->hfile);
  256.     LocalFreePtr((void NEAR *)OFFSETOF(gfile));
  257.     return;
  258. }
  259.  
  260. /* returns number of characters read */
  261. int
  262. Gfgets(LPSTR lp, int size, GFILE *gfile)
  263. {
  264. int i;
  265. int ch;
  266.     for (i=0; i<size; i++) {
  267.         if (gfile->getleft <= 0) {
  268.             if ( (gfile->getleft = _lread(gfile->hfile, gfile->getbuf, GBUFSIZE)) == 0)
  269.                 break;
  270.             gfile->getnext = 0;
  271.         }
  272.         ch = *lp++ = gfile->getbuf[gfile->getnext++];
  273.         gfile->getleft --;
  274.         if (ch == '\r') {
  275.             i--;
  276.             lp--;
  277.         }
  278.         if (ch == '\n') {
  279.             i++;
  280.             break;
  281.         }
  282.     }
  283.     if (i<size)
  284.         *lp++ = '\0';
  285.     return i;
  286. }
  287.  
  288. /* Get a line from the menu file */
  289. /* Return number of lines read from file including comment lines */
  290. int GetLine(char * buffer, int len, GFILE *gfile)
  291. {
  292. BOOL  status;
  293. int nLine = 0;
  294.     
  295.    status = (Gfgets(buffer,len,gfile) != 0);
  296.    nLine++;
  297.    while( status && ( buffer[0] == NULL || buffer[0] == '\n' || buffer[0] == ';' ) ) {
  298.       /* blank line or comment - ignore */ 
  299.          status = (Gfgets(buffer,len,gfile) != 0);
  300.       nLine++;
  301.    }
  302.    if (lstrlen(buffer)>0)
  303.       buffer[lstrlen(buffer)-1] = '\0';    /* remove trailing \n */
  304.  
  305.    if (!status)
  306.       nLine = 0;    /* zero lines if file error */
  307.         
  308.     return nLine;
  309. }
  310.  
  311. /* Left justify string */
  312. void LeftJustify(char *d, char *s)
  313. {
  314.     while ( *s && (*s==' ' || *s=='\t') )
  315.         s++;    /* skip over space */
  316.     do {
  317.         *d++ = *s;
  318.     } while (*s++);
  319. }
  320.  
  321. /* Translate string to tokenized macro */
  322. void TranslateMacro(char *string)
  323. {
  324. int i, len;
  325. LPSTR ptr;
  326.  
  327.     for( i=0; keyword[i]!=(char *)NULL; i++ ) {
  328.         if( (ptr = _fstrstr( string, keyword[i] )) != NULL ) {
  329.             len = lstrlen( keyword[i] );
  330.             *ptr = keyeq[i];
  331.             lstrcpy( ptr+1, ptr+len );
  332.             i--;       /* allows for more than one occurrence of keyword */
  333.             }
  334.         }
  335. }
  336.  
  337. /* Load Macros, and create Menu from Menu file */
  338. void 
  339. LoadMacros(LPTW lptw)
  340. {
  341. GFILE *menufile;
  342. BYTE FAR *macroptr;
  343. char *buf;
  344. int nMenuLevel;
  345. HMENU hMenu[MENUDEPTH+1];
  346. LPMW lpmw;
  347. int nLine = 1;
  348. int nInc;
  349. HGLOBAL hmacro, hmacrobuf;
  350.  
  351. int i;
  352. HDC hdc;
  353. TEXTMETRIC tm;
  354. RECT rect;
  355. int ButtonX, ButtonY;
  356. char FAR *ButtonText[BUTTONMAX];
  357.  
  358.     lpmw = lptw->lpmw;
  359.  
  360.     /* mark all buffers and menu file as unused */
  361.     buf = (char *)NULL;
  362.     hmacro = 0;
  363.     hmacrobuf = 0;
  364.     lpmw->macro = (BYTE FAR * FAR *)NULL;
  365.     lpmw->macrobuf = (BYTE FAR *)NULL;
  366.     lpmw->szPrompt = (char *)NULL;
  367.     lpmw->szAnswer = (char *)NULL;
  368.     menufile = (GFILE *)NULL;
  369.  
  370.     /* open menu file */
  371.     if ((menufile=Gfopen(lpmw->szMenuName,READ)) == (GFILE *)NULL)
  372.         goto errorcleanup;
  373.  
  374.     /* allocate buffers */
  375.     if ((buf = LocalAllocPtr(LHND, MAXSTR)) == (char *)NULL)
  376.         goto nomemory;
  377.     hmacro = GlobalAlloc(GHND,(NUMMENU) * sizeof(BYTE FAR *));
  378.     if ((lpmw->macro = (BYTE FAR * FAR *)GlobalLock(hmacro))  == (BYTE FAR * FAR *)NULL)
  379.         goto nomemory;
  380.     hmacrobuf = GlobalAlloc(GHND, MACROLEN);
  381.     if ((lpmw->macrobuf = (BYTE FAR*)GlobalLock(hmacrobuf)) == (BYTE FAR *)NULL)
  382.         goto nomemory;
  383.     if ((lpmw->szPrompt = LocalAllocPtr(LHND, MAXSTR)) == (char *)NULL)
  384.         goto nomemory;
  385.     if ((lpmw->szAnswer = LocalAllocPtr(LHND, MAXSTR)) == (char *)NULL)
  386.         goto nomemory;
  387.  
  388.     macroptr = lpmw->macrobuf;
  389.     lpmw->nButton = 0;
  390.     lpmw->nCountMenu = 0;
  391.     lpmw->hMenu = hMenu[0] = CreateMenu();
  392.     nMenuLevel = 0;
  393.  
  394.     while ((nInc = GetLine(buf,MAXSTR,menufile)) != 0) {
  395.       nLine += nInc;
  396.       LeftJustify(buf,buf);
  397.       if (buf[0]=='\0') {
  398.         /* ignore blank lines */
  399.       }
  400.       else if (!lstrcmpi(buf,"[Menu]")) {
  401.         /* new menu */
  402.         if (!(nInc = GetLine(buf,MAXSTR,menufile))) {
  403.             nLine += nInc;
  404.             wsprintf(buf,"Problem on line %d of %s\n",nLine,lpmw->szMenuName);
  405.                     MessageBox(lptw->hWndParent,(LPSTR) buf,lptw->Title, MB_ICONEXCLAMATION);
  406.             goto errorcleanup;
  407.         }
  408.         LeftJustify(buf,buf);
  409.         if (nMenuLevel<MENUDEPTH)
  410.             nMenuLevel++;
  411.         else {
  412.             wsprintf(buf,"Menu is too deep at line %d of %s\n",nLine,lpmw->szMenuName);
  413.                     MessageBox(lptw->hWndParent,(LPSTR) buf,lptw->Title, MB_ICONEXCLAMATION);
  414.             goto errorcleanup;
  415.         }
  416.         hMenu[nMenuLevel] = CreateMenu();
  417.         AppendMenu(hMenu[nMenuLevel > 0 ? nMenuLevel-1 : 0],
  418.             MF_STRING | MF_POPUP, (UINT)hMenu[nMenuLevel], (LPCSTR)buf);
  419.       }
  420.       else if (!lstrcmpi(buf,"[EndMenu]")) {
  421.         if (nMenuLevel > 0)
  422.             nMenuLevel--;    /* back up one menu */
  423.       }
  424.       else if (!lstrcmpi(buf,"[Button]")) {
  425.         /* button macro */
  426.         if (lpmw->nButton >= BUTTONMAX) {
  427.             wsprintf(buf,"Too many buttons at line %d of %s\n",nLine,lpmw->szMenuName);
  428.                        MessageBox(lptw->hWndParent,(LPSTR) buf,lptw->Title, MB_ICONEXCLAMATION);
  429.             goto errorcleanup;
  430.         }
  431.         if (!(nInc = GetLine(buf,MAXSTR,menufile))) {
  432.             nLine += nInc;
  433.             wsprintf(buf,"Problem on line %d of %s\n",nLine,lpmw->szMenuName);
  434.                     MessageBox(lptw->hWndParent,(LPSTR) buf,lptw->Title, MB_ICONEXCLAMATION);
  435.             goto errorcleanup;
  436.         }
  437.         LeftJustify(buf,buf);
  438.         if (lstrlen(buf)+1 < MACROLEN - (macroptr-lpmw->macrobuf))
  439.             lstrcpy((char FAR *)macroptr,buf);
  440.         else {
  441.             wsprintf(buf,"Out of space for storing menu macros\n at line %d of \n",nLine,lpmw->szMenuName);
  442.                        MessageBox(lptw->hWndParent,(LPSTR) buf,lptw->Title, MB_ICONEXCLAMATION);
  443.             goto errorcleanup;
  444.         }
  445.         ButtonText[lpmw->nButton] = (char FAR *)macroptr;
  446.         macroptr += lstrlen((char FAR *)macroptr)+1;
  447.         *macroptr = '\0';
  448.         if (!(nInc = GetLine(buf,MAXSTR,menufile))) {
  449.             nLine += nInc;
  450.             wsprintf(buf,"Problem on line %d of %s\n",nLine,lpmw->szMenuName);
  451.                        MessageBox(lptw->hWndParent,(LPSTR) buf,lptw->Title, MB_ICONEXCLAMATION);
  452.             goto errorcleanup;
  453.         }
  454.         LeftJustify(buf,buf);
  455.         TranslateMacro(buf);
  456.         if (lstrlen(buf)+1 < MACROLEN - (macroptr-lpmw->macrobuf))
  457.             lstrcpy((char FAR *)macroptr,buf);
  458.         else {
  459.             wsprintf(buf,"Out of space for storing menu macros\n at line %d of \n",nLine,lpmw->szMenuName);
  460.                        MessageBox(lptw->hWndParent,(LPSTR) buf,lptw->Title, MB_ICONEXCLAMATION);
  461.             goto errorcleanup;
  462.         }
  463.         lpmw->hButtonID[lpmw->nButton] = lpmw->nCountMenu;
  464.         lpmw->macro[lpmw->nCountMenu] = macroptr;
  465.         macroptr += lstrlen((char FAR *)macroptr)+1;
  466.         *macroptr = '\0';
  467.         lpmw->nCountMenu++;
  468.         lpmw->nButton++;
  469.       }
  470.       else {
  471.         /* menu item */
  472.         if (lpmw->nCountMenu>=NUMMENU) {
  473.             wsprintf(buf,"Too many menu items at line %d of %s\n",nLine,lpmw->szMenuName);
  474.                        MessageBox(lptw->hWndParent,(LPSTR) buf,lptw->Title, MB_ICONEXCLAMATION);
  475.             goto errorcleanup;
  476.         }
  477.         LeftJustify(buf,buf);
  478.         if (buf[0]=='-') {
  479.             if (nMenuLevel == 0)
  480.             AppendMenu(hMenu[0], MF_MENUBREAK, 0, (LPSTR)NULL);
  481.             else
  482.             AppendMenu(hMenu[nMenuLevel], MF_SEPARATOR, 0, (LPSTR)NULL);
  483.         }
  484.         else if (buf[0]=='|') {
  485.             AppendMenu(hMenu[nMenuLevel], MF_MENUBARBREAK, 0, (LPSTR)NULL);
  486.         }
  487.         else {
  488.             AppendMenu(hMenu[nMenuLevel],MF_STRING, lpmw->nCountMenu, (LPSTR)buf);
  489.             if (!(nInc = GetLine(buf,MAXSTR,menufile))) {
  490.                 nLine += nInc;
  491.                 wsprintf(buf,"Problem on line %d of %s\n",nLine,lpmw->szMenuName);
  492.                         MessageBox(lptw->hWndParent,(LPSTR) buf,lptw->Title, MB_ICONEXCLAMATION);
  493.                 goto errorcleanup;
  494.             }
  495.             LeftJustify(buf,buf);
  496.             TranslateMacro(buf);
  497.             if (lstrlen(buf)+1 < MACROLEN - (macroptr-lpmw->macrobuf))
  498.                 lstrcpy((char FAR *)macroptr,buf);
  499.             else {
  500.                 wsprintf(buf,"Out of space for storing menu macros\n at line %d of %s\n",nLine,lpmw->szMenuName);
  501.                         MessageBox(lptw->hWndParent,(LPSTR) buf,lptw->Title, MB_ICONEXCLAMATION);
  502.                 goto errorcleanup;
  503.             }
  504.             lpmw->macro[lpmw->nCountMenu] = macroptr;
  505.             macroptr += lstrlen((char FAR *)macroptr)+1;
  506.             *macroptr = '\0';
  507.             lpmw->nCountMenu++;
  508.         }
  509.       }
  510.     }
  511.  
  512.     if ( (lpmw->nCountMenu - lpmw->nButton) > 0 ) {
  513.         /* we have a menu bar so put it on the window */
  514.         SetMenu(lptw->hWndParent,lpmw->hMenu);
  515.         DrawMenuBar(lptw->hWndParent);
  516.     }
  517.  
  518.     if (!lpmw->nButton)
  519.         goto cleanup;        /* no buttons */
  520.  
  521.     /* calculate size of buttons */
  522.     hdc = GetDC(lptw->hWndParent);
  523.     SelectFont(hdc, GetStockFont(SYSTEM_FIXED_FONT));
  524.     GetTextMetrics(hdc, &tm);
  525.     ButtonX = 8 * tm.tmAveCharWidth;
  526.     ButtonY = 6 * (tm.tmHeight + tm.tmExternalLeading) / 4;
  527.     ReleaseDC(lptw->hWndParent,hdc);
  528.  
  529.     /* move top of client text window down to allow space for buttons */
  530.     lptw->ButtonHeight = ButtonY+1;
  531.     GetClientRect(lptw->hWndParent, &rect);
  532.     SetWindowPos(lptw->hWndText, (HWND)NULL, 0, lptw->ButtonHeight,
  533.             rect.right, rect.bottom-lptw->ButtonHeight, 
  534.             SWP_NOZORDER | SWP_NOACTIVATE);
  535.  
  536.     /* create the buttons */
  537. #ifdef __DLL__
  538.     lpmw->lpfnMenuButtonProc = (WNDPROC)GetProcAddress(hdllInstance, "MenuButtonProc");
  539. #else
  540.     lpmw->lpfnMenuButtonProc = (WNDPROC)MakeProcInstance((FARPROC)MenuButtonProc, hdllInstance);
  541. #endif
  542.     for (i=0; i<lpmw->nButton; i++) {
  543.         lpmw->hButton[i] = CreateWindow("button", ButtonText[i],
  544.             WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
  545.                 i * ButtonX, 0,
  546.                 ButtonX, ButtonY,
  547.                 lptw->hWndParent, (HMENU)i,
  548.                 lptw->hInstance, lptw);
  549.         lpmw->lpfnButtonProc[i] = (WNDPROC) GetWindowLong(lpmw->hButton[i], GWL_WNDPROC);
  550.         SetWindowLong(lpmw->hButton[i], GWL_WNDPROC, (LONG)lpmw->lpfnMenuButtonProc);
  551.     }
  552.  
  553.     goto cleanup;
  554.  
  555.  
  556. nomemory:
  557.     MessageBox(lptw->hWndParent,"Out of memory",lptw->Title, MB_ICONEXCLAMATION);
  558. errorcleanup:
  559.     if (hmacro) {
  560.         GlobalUnlock(hmacro);
  561.         GlobalFree(hmacro);
  562.     }
  563.     if (hmacrobuf) {
  564.         GlobalUnlock(hmacrobuf);
  565.         GlobalFree(hmacrobuf);
  566.     }
  567.     if (lpmw->szPrompt != (char *)NULL)
  568.         LocalFreePtr((void NEAR *)OFFSETOF(lpmw->szPrompt));
  569.     if (lpmw->szAnswer != (char *)NULL)
  570.         LocalFreePtr((void NEAR *)OFFSETOF(lpmw->szAnswer));
  571.  
  572. cleanup:
  573.     if (buf != (char *)NULL)
  574.         LocalFreePtr((void NEAR *)OFFSETOF(buf));
  575.     if (menufile != (GFILE *)NULL)
  576.         Gfclose(menufile);
  577.     return;
  578.  
  579. }
  580.  
  581. void
  582. CloseMacros(LPTW lptw)
  583. {
  584. HGLOBAL hglobal;
  585. LPMW lpmw;
  586.     lpmw = lptw->lpmw;
  587.  
  588. #ifndef __DLL__
  589.     if (lpmw->lpfnMenuButtonProc)
  590.         FreeProcInstance((FARPROC)lpmw->lpfnMenuButtonProc);
  591. #endif
  592.     hglobal = (HGLOBAL)GlobalHandle( SELECTOROF(lpmw->macro) );
  593.     if (hglobal) {
  594.         GlobalUnlock(hglobal);
  595.         GlobalFree(hglobal);
  596.     }
  597.     hglobal = (HGLOBAL)GlobalHandle( SELECTOROF(lpmw->macrobuf) );
  598.     if (hglobal) {
  599.         GlobalUnlock(hglobal);
  600.         GlobalFree(hglobal);
  601.     }
  602.     if (lpmw->szPrompt != (char *)NULL)
  603.         LocalFreePtr((void NEAR *)OFFSETOF(lpmw->szPrompt));
  604.     if (lpmw->szAnswer != (char *)NULL)
  605.         LocalFreePtr((void NEAR *)OFFSETOF(lpmw->szAnswer));
  606. }
  607.  
  608.  
  609. /***********************************************************************/
  610. /* InputBoxDlgProc() -  Message handling routine for Input dialog box         */
  611. /***********************************************************************/
  612.  
  613. BOOL CALLBACK _export
  614. InputBoxDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  615. {
  616. LPTW lptw;
  617. LPMW lpmw;
  618.     lptw = (LPTW)GetWindowLong(GetParent(hDlg), 0);
  619.     lpmw = lptw->lpmw;
  620.  
  621.     switch( message) {
  622.         case WM_INITDIALOG:
  623.             SetDlgItemText( hDlg, ID_PROMPT, lpmw->szPrompt);
  624.             return( TRUE);
  625.  
  626.         case WM_COMMAND:
  627.             switch(LOWORD(wParam)) {
  628.                 case ID_ANSWER:
  629.                     return( TRUE);
  630.  
  631.                 case IDOK:
  632.                     lpmw->nChar = GetDlgItemText( hDlg, ID_ANSWER, lpmw->szAnswer, MAXSTR);
  633.                     EndDialog( hDlg, TRUE);
  634.                     return( TRUE);
  635.  
  636.                 case IDCANCEL:
  637.                     lpmw->szAnswer[0] = NULL;
  638.                     EndDialog( hDlg, FALSE);
  639.                     return( TRUE);
  640.  
  641.                 default:
  642.                     return( FALSE);
  643.                 }
  644.         default:
  645.             return( FALSE);
  646.         }
  647.     }
  648.  
  649.  
  650. LRESULT CALLBACK _export
  651. MenuButtonProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  652. {
  653. LPTW lptw;
  654. LPMW lpmw;
  655. #ifdef WIN32
  656. LONG n = GetWindowLong(hwnd, GWL_ID);
  657. #else
  658. WORD n = GetWindowWord(hwnd, GWW_ID);
  659. #endif
  660.     lptw = (LPTW)GetWindowLong(GetParent(hwnd), 0);
  661.     lpmw = lptw->lpmw;
  662.  
  663.     switch(message) {
  664.         case WM_LBUTTONUP:
  665.             {
  666.             RECT rect;
  667.             POINT pt;
  668.             GetWindowRect(hwnd, &rect);
  669.             GetCursorPos(&pt);
  670.             if (PtInRect(&rect, pt))
  671.                 SendMessage(lptw->hWndText, WM_COMMAND, lpmw->hButtonID[n], 0L);
  672.             SetFocus(lptw->hWndText);
  673.             }
  674.             break;
  675.     }
  676.     return CallWindowProc((lpmw->lpfnButtonProc[n]), hwnd, message, wParam, lParam);
  677. }
  678.